import {Injectable} from '@angular/core';
import {
  ActivatedRouteSnapshot,
  RouterStateSnapshot,
  UrlTree,
  Router,
  CanActivateChild
} from '@angular/router';
import {Observable} from 'rxjs';
import {LoginUserService} from '../services/login-user.service';
import {catchError, map} from 'rxjs/operators';
import {UserMenu} from '../entities/user/user-menu';

@Injectable({
  providedIn: 'root'
})
export class GrantGuardGuard implements CanActivateChild {


  constructor(private loginUserService: LoginUserService, private router: Router) {
  }

  /**
   * 判定是否可以访问 targetUrl
   * 拥有的路径及其子路径都要可以访问，但类似路径不行，比如拥有权限 /index/user ,但要访问的是 /index/userInfo
   * @param targetUrl
   * @param menus
   * @private
   */
  private hasGrant(targetUrl: string, menus: UserMenu[]): boolean {
    if (!targetUrl) {
      return false;
    }
    targetUrl = targetUrl.startsWith('/') ? targetUrl : '/' + targetUrl;

    for (const item of menus) {
      let p = item.path;
      p = p.startsWith('/') ? p : '/' + p;
      if (!p) {
        return false;
      }

      if (p === targetUrl) {
        return true;
      }
      const pTemp = p.endsWith('/') ? p : p + '/';
      targetUrl = targetUrl.endsWith('/') ? targetUrl : targetUrl + '/';
      if (targetUrl.startsWith(pTemp)) {
        return true;
      }
    }
    return false;
  }

  canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot):
    Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
    let target = state.url;
    if (target.indexOf('?') >= 0) {
      target = target.substr(0, target.indexOf('?'));
    }
    console.log('navigate to :', target);

    if (target === '/welcome') {
      return true;
    }

    return this.loginUserService.MENUS
      .pipe(
        map(value => {
          let result;
          if (!value || !value.length) {
            result = false;
          } else {
            result = this.hasGrant(target, value);
          }

          if (!result) {
            this.router.navigate(['/']);
          }

          return result;
        }),
        catchError((error) => {
          console.log(error);
          if (error.status === 'TOKEN_EXPIRED') {
           return  this.router.navigate(['/login']);
          } else {
            throw error;
          }
        })
      );
  }

}
